route.ts 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import { NextRequest, NextResponse } from "next/server";
  2. import { STORAGE_KEY } from "../../../constant";
  3. async function handle(
  4. req: NextRequest,
  5. { params }: { params: { path: string[] } },
  6. ) {
  7. if (req.method === "OPTIONS") {
  8. return NextResponse.json({ body: "OK" }, { status: 200 });
  9. }
  10. const folder = STORAGE_KEY;
  11. const fileName = `${folder}/backup.json`;
  12. const requestUrl = new URL(req.url);
  13. let endpoint = requestUrl.searchParams.get("endpoint");
  14. if (!endpoint?.endsWith("/")) {
  15. endpoint += "/";
  16. }
  17. const endpointPath = params.path.join("/");
  18. // only allow MKCOL, GET, PUT
  19. if (req.method !== "MKCOL" && req.method !== "GET" && req.method !== "PUT") {
  20. return NextResponse.json(
  21. {
  22. error: true,
  23. msg: "you are not allowed to request " + params.path.join("/"),
  24. },
  25. {
  26. status: 403,
  27. },
  28. );
  29. }
  30. // for MKCOL request, only allow request ${folder}
  31. if (
  32. req.method == "MKCOL" &&
  33. !new URL(endpointPath).pathname.endsWith(folder)
  34. ) {
  35. return NextResponse.json(
  36. {
  37. error: true,
  38. msg: "you are not allowed to request " + params.path.join("/"),
  39. },
  40. {
  41. status: 403,
  42. },
  43. );
  44. }
  45. // for GET request, only allow request ending with fileName
  46. if (
  47. req.method == "GET" &&
  48. !new URL(endpointPath).pathname.endsWith(fileName)
  49. ) {
  50. return NextResponse.json(
  51. {
  52. error: true,
  53. msg: "you are not allowed to request " + params.path.join("/"),
  54. },
  55. {
  56. status: 403,
  57. },
  58. );
  59. }
  60. // for PUT request, only allow request ending with fileName
  61. if (
  62. req.method == "PUT" &&
  63. !new URL(endpointPath).pathname.endsWith(fileName)
  64. ) {
  65. return NextResponse.json(
  66. {
  67. error: true,
  68. msg: "you are not allowed to request " + params.path.join("/"),
  69. },
  70. {
  71. status: 403,
  72. },
  73. );
  74. }
  75. const targetUrl = `${endpoint + endpointPath}`;
  76. const method = req.method;
  77. const shouldNotHaveBody = ["get", "head"].includes(
  78. method?.toLowerCase() ?? "",
  79. );
  80. const fetchOptions: RequestInit = {
  81. headers: {
  82. authorization: req.headers.get("authorization") ?? "",
  83. },
  84. body: shouldNotHaveBody ? null : req.body,
  85. method,
  86. // @ts-ignore
  87. duplex: "half",
  88. };
  89. const fetchResult = await fetch(targetUrl, fetchOptions);
  90. console.log("[Any Proxy]", targetUrl, {
  91. status: fetchResult.status,
  92. statusText: fetchResult.statusText,
  93. });
  94. return fetchResult;
  95. }
  96. export const POST = handle;
  97. export const GET = handle;
  98. export const OPTIONS = handle;
  99. export const runtime = "edge";